]> dgit.raspbian.org Git - gnome-shell.git/commitdiff
screenshot: Also do pipeline fallback on screencast crashes during startup
authorJonas Dreßler <verdre@v0yd.nl>
Mon, 2 Oct 2023 12:30:08 +0000 (14:30 +0200)
committerJonas Dreßler <verdre@v0yd.nl>
Sun, 11 Feb 2024 11:36:23 +0000 (12:36 +0100)
Since the last commit, we have infrastructure in place in the ScreencastService
to blocklist pipelines which crashed the recorder.

If such a crash happens a few minutes into a screencast, we can't do any better
than telling the user about the problem and encouraging them to try again (with
the faulty pipeline now blocklisted).

If the crash happens while starting the recording though, we can actually do
better: We can try to auto-restart the ScreencastService ourselves, and the
recording might still succeed without the user noticing anything. So retry
that start of the recorder for two more times, and then finally give up.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2976>

js/ui/screenshot.js

index eb561a3b059d67832a9b443c6a42256a7b872ec2..77d4c0c6f798278b8a24917e87c89404307258e5 100644 (file)
@@ -1116,6 +1116,11 @@ export const ScreenshotUI = GObject.registerClass({
             if (!this._screencastInProgress)
                 return;
 
+            // If the recorder crashed while we're starting it in _startScreencast(),
+            // let the catch-block there handle the error.
+            if (this._screencastStarting)
+                return;
+
             this._screencastFailed(ScreencastPhase.RECORDING,
                 new GLib.Error(ScreencastErrors, ScreencastError.SERVICE_CRASH,
                     'Service crashed'));
@@ -1947,7 +1952,7 @@ export const ScreenshotUI = GObject.registerClass({
             this.emit('screenshot-taken', file);
     }
 
-    async _startScreencast() {
+    async _startScreencast(nRetries = 0) {
         if (this._windowButton.checked)
             return; // TODO
 
@@ -1981,8 +1986,11 @@ export const ScreenshotUI = GObject.registerClass({
         // Set this before calling the method as the screen recording indicator
         // will check it before the success callback fires.
         this._setScreencastInProgress(true);
+        let retry = false;
 
         try {
+            this._screencastStarting = true;
+
             const [, path] = await method(
                 GLib.build_filenamev([
                     /* Translators: this is the folder where recorded
@@ -1998,7 +2006,21 @@ export const ScreenshotUI = GObject.registerClass({
 
             this._screencastPath = path;
         } catch (error) {
-            this._screencastFailed(ScreencastPhase.STARTUP, error);
+            // Recorder service disconnected without reply -> service crash
+            // That should have blocklisted the pipeline that caused the crash,
+            // so try again.
+            if (error.matches(Gio.DBusError, Gio.DBusError.NO_REPLY) && nRetries < 2)
+                retry = true;
+            else
+                this._screencastFailed(ScreencastPhase.STARTUP, error);
+        }
+
+        delete this._screencastStarting;
+
+        if (retry) {
+            console.log('Screencast service crashed during startup, trying again');
+            this._setScreencastInProgress(false);
+            this._startScreencast(nRetries + 1);
         }
     }